﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Windows.Input;
using Cinch;
using System.Collections;
using CodeStash.Common.DTOS;
using System.ComponentModel.Composition;
using MEFedMVVM.ViewModelLocator;
using CodeStash.Addin.Core.Interfaces;
using System.ComponentModel;
using System.Net;

namespace CodeStash.Addin.ViewModels
{

    [ExportViewModel("SearchResultsViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class SearchResultsViewModel : ViewModelBase
    {
        #region Data
        private JSONCodeSnippet selectedSnippet = null;
        private IUIVisualizerService uiVisualizerService;
        private IDocumentService documentService;
        private int pageSize;
        private int totalPagesNeeded = 1;
        private IEnumerable<int> totalPages;
        private int currentPage = 1;
        #endregion

        #region Ctor
        [ImportingConstructor]
        public SearchResultsViewModel(
            IUIVisualizerService uiVisualizerService, 
            IDocumentService documentService,
            IRestService restService)
        {
            this.uiVisualizerService = uiVisualizerService;
            this.documentService = documentService;
            this.pageSize = restService.PageSize;

            Mediator.Instance.Register(this);
            ViewCurrentCommand = new SimpleCommand<object, object>(ExecuteShowCurrent);
            InsertCurrentCommand = new SimpleCommand<object, object>(ExecuteInsertCurrent);
            ShowLastPageCommand = new SimpleCommand<object, object>(ExecuteShowLastPageCommand);
            ShowFirstPageCommand = new SimpleCommand<object, object>(ExecuteShowFirstPageCommand);
        }
        #endregion

        #region Public Properties

        /// <summary>
        /// View Current snippet Command
        /// </summary>
        public ICommand ViewCurrentCommand { get; set; }

        /// <summary>
        /// Insert Current Command
        /// </summary>        
        public ICommand InsertCurrentCommand { get; set; }

        /// <summary>
        /// Show Last Page Command
        /// </summary>        
        public ICommand ShowLastPageCommand { get; set; }

        /// <summary>
        /// Show First Page Command
        /// </summary>        
        public ICommand ShowFirstPageCommand { get; set; }

        /// <summary>
        /// Gets or sets the results to show
        /// </summary>
        static PropertyChangedEventArgs resultsArgs =
            ObservableHelper.CreateArgs<SearchResultsViewModel>(x => x.Results);

        public JSONPagesSearchResultCodeSnippet Results { get; private set; }

        /// <summary>
        /// Gets the text to show for "View" link
        /// </summary>     
        public static string ViewLinkText
        {
            get { return "View Snippet"; }
        }

        /// <summary>
        /// Gets the text to show for "Insert" link
        /// </summary>
        public static string InsertLinkText
        {
            get { return "Insert Snippet"; }
        }

        /// <summary>
        /// Gets the total number of pages
        /// </summary>
        static PropertyChangedEventArgs totalPagesArgs =
            ObservableHelper.CreateArgs<SearchResultsViewModel>(x => x.TotalPages);

        public IEnumerable<int> TotalPages
        {
            get { return totalPages; }
        }

        /// <summary>
        /// Returns true if there are results to show
        /// </summary>
        static PropertyChangedEventArgs hasResultsArgs =
            ObservableHelper.CreateArgs<SearchResultsViewModel>(x => x.HasResults);
        
        public bool HasResults
        {
            get { return Results != null && Results.PagedMatchedSnippets != null && Results.PagedMatchedSnippets.Any(); }
        }

        /// <summary>
        /// Gets of sets the CurrentPage
        /// </summary>
        static PropertyChangedEventArgs currentPageArgs =
            ObservableHelper.CreateArgs<SearchResultsViewModel>(x => x.CurrentPage);

        public int CurrentPage
        {
            get { return currentPage; }
            set
            {
                if (currentPage != value)
                {
                    currentPage = value;
                    NotifyPropertyChanged(currentPageArgs);
                    Mediator.Instance.NotifyColleagues<int>("FetchPageOfSearchResults", currentPage);
                }
            }
        }

        /// <summary>
        /// Gets or sets the SelectedSnippet
        /// </summary>
        static PropertyChangedEventArgs selectedSnippetArgs =
            ObservableHelper.CreateArgs<SearchResultsViewModel>(x => x.SelectedSnippet);
        
        public JSONCodeSnippet SelectedSnippet
        {
            get { return selectedSnippet; }
            set
            {
                if (selectedSnippet != value)
                {
                    selectedSnippet = value;
                    base.NotifyPropertyChanged(selectedSnippetArgs);
                }
            }
        }
        #endregion

        #region Mediator Messages
        private string Decode(string item)
        {
            return WebUtility.HtmlDecode(item);
        }

        [MediatorMessageSink("DisplaySearchResults")]
        private void OnDisplaySearchResults(JSONPagesSearchResultCodeSnippet results)
        {
            Results = results;


            totalPagesNeeded = 1;
            if (Results != null)
            {
                if (Results.TotalAmountOfSnippetsThatMatchedSearch > pageSize)
                {
                    totalPagesNeeded = (Results.TotalAmountOfSnippetsThatMatchedSearch % pageSize) > 0 ?
                        (int)Math.Floor((double)(Results.TotalAmountOfSnippetsThatMatchedSearch / pageSize) + 1) :
                        (int)Math.Floor((double)(Results.TotalAmountOfSnippetsThatMatchedSearch / pageSize));
                }

                totalPages = Enumerable.Range(1, totalPagesNeeded);
            }
            base.NotifyPropertyChanged(resultsArgs);
            base.NotifyPropertyChanged(hasResultsArgs);
            base.NotifyPropertyChanged(totalPagesArgs);
        }


        [MediatorMessageSink("DisplayPagedSearchResults")]
        private void OnDisplayPagedSearchResults(JSONPagesSearchResultCodeSnippet results)
        {
            Results = results;
            base.NotifyPropertyChanged(resultsArgs);
            base.NotifyPropertyChanged(hasResultsArgs);
        }
        #endregion

        #region Command Handlers

        #region ShowCurrent
        private void ExecuteShowCurrent(object parameter)
        {
            uiVisualizerService.ShowDialog("SnippetPopup", SelectedSnippet);
        }
        #endregion

        #region InsertCurrent
        private void ExecuteInsertCurrent(object parameter)
        {
            try
            {
                documentService.InsertText(WebUtility.HtmlDecode(SelectedSnippet.ActualCode));
                Mediator.Instance.NotifyColleagues<bool>("CloseSearchViewPopup", true);
            }
            catch 
            {
            }
        }
        #endregion

        #region ShowFirstPageCommand
        private void ExecuteShowFirstPageCommand(object parameter)
        {
            if (HasResults)
            {
                CurrentPage = 1;
            }
        }
        #endregion

        #region ShowLastPageCommand
        private void ExecuteShowLastPageCommand(object parameter)
        {
            if(HasResults)
            {
                CurrentPage = totalPagesNeeded;
            }
        }
        #endregion
       
        #endregion
    }

}
